#include "../inc/clientbase.h"
#include "client_impl.h"
#include "client_config.h"
#include "../inc/logger.h"
#include "subscription.h"
#include "publishdata.h"
#include "../core/command_config.h"

#include <functional>
#ifdef _WIN32
using namespace std::tr1::placeholders;
#elif __linux__
using namespace std::placeholders;
#endif

DataBusClient::DataBusClient()
{
	m_pAppServer=new AppServerImpl();
	m_pAppServer->onCreateMessage=bind(&DataBusClient::CreateMessage,this,_1);
    //m_pAppServer->onMessage=bind(&DataBusClient::OnMessage,this,_1);
	//m_pAppServer->onPublish = bind(&DataBusClient::OnPublishInternal, this, _1);
    //m_pAppServer->onEvent=bind(&DataBusClient::OnEvent,this,_1);
}

DataBusClient::~DataBusClient()
{
	m_pAppServer->onCreateMessage = nullptr;
	m_pAppServer->onMessage = nullptr;
	m_pAppServer->onPublish = nullptr;
	m_pAppServer->onEvent = nullptr;
	m_pAppServer->onRequest = nullptr;
	delete m_pAppServer;
}

void DataBusClient::SetRequestCallback(function<void(PackagePtr)> requestcb)
{
	m_pAppServer->onRequest = requestcb;
}
void DataBusClient::SetPublishCallback(function<void(PackagePtr)> publishcb)
{
	m_pAppServer->onPublish = publishcb;
}
void DataBusClient::SetEventCallback(function<void(int)> eventcb)
{
	m_pAppServer->onEvent = eventcb;
}
void DataBusClient::SetCreateMessageCallback(function<MessagePtr(const std::string&)> createcb)
{
	m_pAppServer->onCreateMessage = createcb;
}
void DataBusClient::OnPublishInternal(PackagePtr pubData)
{
	//if (pubData->classtype().compare(MsgExpress::PublishData::default_instance().GetTypeName()) == 0)
	//	OnPublish(dynamic_pointer_cast<MsgExpress::PublishData>(pubData->message()));
	OnPublish(pubData);
}
void DataBusClient::OnPublish(PackagePtr pubData)
{

}
//void DataBusClient::OnPublish(PublishPtr pubData)
//{
//	//LOG4_INFO("Receive publish,topic:%d",pubData->topic());
//}
void DataBusClient::OnMessage(PackagePtr package)
{

}
void DataBusClient::OnEvent(int eventId)
{

}
int DataBusClient::Initialize(ClientCFG* clientCfg,ProxyCFG* proxyCfg)
{
	return m_pAppServer->Initialize(clientCfg,proxyCfg);
}
int  DataBusClient::Initialize(const char* configPath,ProxyCFG* proxyCfg)
{
	if(configPath)
	    XMLConfig::SetPath(configPath);

	/*string xml_file = "Command.xml";
	CommandConfig &cconf=CommandConfig::getInstance();
	if(!cconf.LoadFile(xml_file))
	{   
		LOG4_ERROR("read client command config file error");
		return -1;
	}  */

	string xml_file = "clientcfg.xml";
	ClientConfig sconf;
	if(!sconf.LoadFile(xml_file))
	{   
		LOG4_ERROR("read client config file error");
		return 0;
	}  
	
	return m_pAppServer->Initialize(&sconf.clientCfg,proxyCfg);
}
int  DataBusClient::Initialize(const wchar_t* configPath,ProxyCFG* proxyCfg)
{
	if(configPath)
	{
#ifdef _WIN32
	    char chPath[MAX_PATH];
	    WideCharToMultiByte(CP_ACP, 0, configPath, -1, chPath, MAX_PATH, NULL, NULL );   
	    return Initialize(chPath,proxyCfg);
#else
		return Initialize();
#endif
	}
	return Initialize();
}
bool  DataBusClient::Release()
{
	return m_pAppServer->Release();
}
MsgExpress::ErrMessage DataBusClient::GetLatestError()
{
	return m_pAppServer->GetLatestError();
}
void DataBusClient::ClearLatestError()
{
	m_pAppServer->ClearLatestError();
}
unsigned int DataBusClient::GetAddress()
{
	return m_pAppServer->GetAddress();
}
uint64_t DataBusClient::GetBrokerTime()
{
	return m_pAppServer->GetBrokerTime();
}
int DataBusClient::GetQueueSize()
{
	return ((AppServerImpl*)m_pAppServer)->GetQueueSize();
}

string  DataBusClient::GetServerIp()
{
	/*string xml_file = "clientcfg.xml";
	ClientConfig &sconf=ClientConfig::Instance();
	if(!sconf.LoadFile(xml_file))
	{   
			LOG4_ERROR("read client xml config file error");
			return "failed";
	}
	if(sconf.clientCfg.serverGroup.size()>0)
	    return sconf.clientCfg.serverGroup[0].serverIP;*/
	return "";
}
void DataBusClient::ReportServerEvent(int code, const string& status)
{
	((AppServerImpl*)m_pAppServer)->ReportServerEvent(code, status);
}
void DataBusClient::RegisterService(int serviceid, const vector<string>& vecclassname)
{
    CommandConfig::getInstance().Register(serviceid, vecclassname);
	MsgExpress::RegisterService regservice;
	regservice.set_serviceid(serviceid);
	for (int i = 0; i < vecclassname.size(); i++)
	{
		regservice.add_functions(vecclassname[i]);
	}
	m_pAppServer->PostMessage(regservice);
}
unsigned int DataBusClient::GetCommand(const char* clazz)
{
	int cmd=0;
	try{
	    cmd=CommandConfig::getInstance().GetCommand(clazz);
	}
	catch(char* err)
	{
		LOG4_ERROR("Class type to command failed,msg:%s",err);
	}
	return cmd;
}
string DataBusClient::GetClazz(unsigned int cmd)
{
	return CommandConfig::getInstance().GetClass(cmd);
}
unsigned int  DataBusClient::PostMsg(const Message& msg,int appId,unsigned int dstaddr)
{
	return m_pAppServer->PostMessage(msg,appId,dstaddr);
}
unsigned int  DataBusClient::PostMsg(int cmd,const char* buff,unsigned int size,Options opt)
{
	return m_pAppServer->PostMessage(cmd,buff,size,opt);
}
bool  DataBusClient::PostMsg(MessagePtr msg,function<void(const MsgParams&)> msgcb,void* arg,unsigned int msTimeout,Options opt)
{
	return m_pAppServer->PostMessage(msg,msgcb,arg,msTimeout,opt);
}
bool DataBusClient::Reply(PackagePtr requestPackage,const Message& replyMsg)
{
	return m_pAppServer->Reply(requestPackage,replyMsg);
}
bool DataBusClient::Reply(PackagePtr requestPackage,const char* buff,unsigned int size)
{
	return m_pAppServer->Reply(requestPackage->header(),buff,size);
}
bool DataBusClient::Reply(PackagePtr requestPackage,unsigned int errCode,string errMsg)
{
	return m_pAppServer->Reply(requestPackage,errCode,errMsg);
}
bool DataBusClient::SendMsg(const Message& request, MessagePtr& response,unsigned int milliseconds,Options options)
{
	return m_pAppServer->SendMessage(request,response,milliseconds,options);
}
bool DataBusClient::SendMsg(unsigned int cmd,const char* srcBuff,unsigned int srcSize,PackageHeader& retHeader,string& retData,unsigned int milliseconds,unsigned int dstaddr)
{
	return m_pAppServer->SendMessage(cmd,srcBuff,srcSize,retHeader,retData,milliseconds,dstaddr);
}
//
//bool DataBusClient::Subscribe(const MsgExpress::SubscribeData& subData, MessagePtr& response)
//{
//	return m_pAppServer->Subscribe(subData,response);
//}
//bool DataBusClient::UnSubscribe(const MsgExpress::UnSubscribeData& subData, MessagePtr& response)
//{
//	return m_pAppServer->UnSubscribe(subData,response);
//}
//bool DataBusClient::ComplexSubscribe(const MsgExpress::ComplexSubscribeData& subData, MessagePtr& response)
//{
//	return m_pAppServer->ComplexSubscribe(subData,response);
//}
bool DataBusClient::Subscribe(int subid, const Message& subData, MessagePtr& response, AppAddress addr )
{
	return m_pAppServer->Subscribe(subid,subData,response,addr);
}
bool DataBusClient::Subscribe(int subid,  const vector<string>& topics, MessagePtr& response, AppAddress addr)
{
	return m_pAppServer->Subscribe(subid, topics, response, addr);
}
bool DataBusClient::Subscribe(int subid, const vector<MessagePtr>& vecSubmsg, MessagePtr& response, AppAddress addr)
{
	return m_pAppServer->Subscribe(subid,vecSubmsg,response,addr);
}
bool DataBusClient::UnSubscribe(int subid, MessagePtr& response)
{
	return m_pAppServer->UnSubscribe(subid,response);
}

bool DataBusClient::Publish(MessagePtr msg,function<void(const MsgParams&)> msgcb,void* arg,unsigned int msTimeout)
{
	return m_pAppServer->Publish(msg,msgcb,arg,msTimeout);
}
//bool DataBusClient::Publish(const MsgExpress::PublishData& pubData)
//{
//	MsgExpress::PublishData* pub = new MsgExpress::PublishData(pubData);
//	return m_pAppServer->Publish(MessagePtr(pub), nullptr, nullptr);
//}
//void DataBusClient::SetDataManager(IDataManager* manager)
//{
//	m_pAppServer->SetDataManager(manager);
//}
//IDataManager* DataBusClient::GetDataManager()
//{
//	return m_pAppServer->GetDataManager();
//}
